#include "string.h"
#include "sys.h"
int strcmp(char *a, char *b) {
  while (*a && *b) {
    if (*a - *b)
      return *a - *b;
    ++a, ++b;
  }
  return *a || *b;
}

int strncmp(char *a, char *b, unsigned n) {
  while (*a && *b && n) {
    if (*a - *b)
      return *a - *b;
    ++a, ++b;
    n--;
  }
  return *a || *b;
}

unsigned strlen(char *s) {
  int cnt = 0;
  while (*s) {
    ++cnt;
    ++s;
  }
  return cnt;
}

int strStr(char *haystack, char *needle) {
  int m = strlen(needle);
  if (m == 0)
    return 0;
  int n = strlen(haystack);
  int next[m];
  next[0] = 0;
  for (int i = 1, j = 0; i < m; i++) {
    while (j > 0 && needle[i] != needle[j])
      j = next[j - 1];
    if (needle[i] == needle[j])
      j++;
    next[i] = j;
  }
  for (int i = 0, j = 0; i < n; i++) {
    while (j > 0 && haystack[i] != needle[j])
      j = next[j - 1];
    if (haystack[i] == needle[j])
      j++;
    if (j == m)
      return i - m + 1;
  }
  return -1;
}
//将src字符串连接到dest的尾部，‘\0’也会追加过去,返回dest首地址，不考虑溢出
char *strcpy(char *des, const char *str) {
  char *tmp = des; //先保存一下原地址
  while (*str != '\0') {
    *des = *str;
    ++des;
    ++str;
  }
  *des = '\0'; //最后将'\0'也拷贝过去
  return tmp;
}

//如果在src指向的数组中遇到一个空字符
//'\0'，则strncpy函数为dest指向的数组添加空字符直到写完n个字符的总数量。
char *strncpy(char *dest, const char *src, unsigned cnt) {

  char *retAddr = dest;

  while (cnt && (*dest++ = *src++))
    cnt--;

  if (cnt) {
    while (--cnt) {
      *dest++ = '\0';
    }
  }
  return retAddr;
}

void *memcpy(void *str1, const void *str2, int size) // size字节数
{
  for (int i = 0; i < size; i++) {
    *((char *)str1 + i) = *((char *)str2 + i);
  }
  return str1;
}

void *memset(void *ptr, int val, unsigned num) {
  unsigned char ch = val; //截断，只保留8位无符号类型
  for (unsigned i = 0; i < num; i++) {
    *((char *)ptr + i) = ch;
  }
  return ptr;
}
//将字符串str2添加到字符串str1的尾部，也就是拼接两个字符串,!!不考虑越界
char *strcat(char *dest, const char *src) {
  if (!dest || !src) {
    return NULL;
  }
  int len = strlen(dest);
  int i = 0;
  while (src[i] != '\0') {
    dest[len + i] = src[i];
    ++i;
  }
  dest[len + i] = '\0';
  return dest;
}

char *strncat(char *strDes, const char *strSrc, unsigned cnt) {
  char *retAddr = strDes;

  while (*strDes)
    strDes++;

  while (cnt--)
    if (!(*strDes++ = *strSrc++)) //注意
      return retAddr;

  *strDes = '\0';
  return retAddr;
}
//字符串分割
/*char *strtok(char *str, const char *s) {
  if (!str || !s) {
    return NULL;
  }
  static char *last = NULL;
  static int p = 0;
  static int a[100] = {0};
  if (str == NULL && last == NULL)
    return NULL;

  if (last != NULL) {
    p++;
    last = last + a[p] - a[p - 1];
    return (last + 1);
  }

  int lenstr = strlen(str);
  int lens = strlen(s);

  int m = 0;
  int n = 0;
  int i = 0;
  for (m = 0; m < lenstr; m++) {
    for (n = 0; n < lens; n++) {
      if (str[m] == s[n]) {
        str[m] = '\0';
        a[i] = m;
        ++i;
        ++m;
        break;
      }
    }
  }
  last = str;
  return last;
}*/

char *strchr(const char *str, int value) {
  if (str == NULL)
    return NULL;
  char c = (char)value;
  while (*str != c && *str++)
    ;
  if (*--str == '\0')
    return NULL;
  return (char *)++str;
}

char *strrchr(char *str, int character) {
  if (str == NULL)
    return NULL;
  char c = (char)character;
  register int i = 0;
  while (*(str + i++))
    ;
  while (--i && *(str + i) != c)
    ;
  if (i == 0) { //下标为0时未比较
    if (*str == c)
      return str;
    else
      return NULL;
  }
  return str + i;
}

size_t strcspn(const char *str1, const char *str2) {
  const char *s = str1, *key;
  while (*s) {
    key = str2;
    while (*key && *s != *key)
      key++;
    if (*key)
      return (s - str1);
    s++;
  }
  return (s - str1);
}

size_t strspn(const char *str1, const char *str2) {
  if (str1 == NULL || str2 == NULL)
    return 0;
  register int j;
  int i = 0;
  int n = 0;
  while (*(str2 + n++))
    ;
  n--; // n->'\0'
  while (*(str1 + i)) {
    j = 0;
    while (*(str2 + j++) != *(str1 + i)) {
      if (j == n)
        return i;
    }
    i++;
  }
  return i;
}

char *strtok(char *str, const char *delimiters) {
  if (delimiters == NULL)
    return NULL;
  static char *s_mem = NULL;
  if (str == NULL && s_mem == NULL)
    return NULL;

  char *s;
  if (str != NULL)
    s = str;
  else
    s = s_mem; //在str ==
               // NULL的情况下，s_mem一定不等于NULL，因为上面的那个if判断
  char const *delim;

  //找到token的起始位置
  int stat = 1;
  while (stat) {
    delim = delimiters; // 一开始没写这句，这里不赋初值怎么在stat里面使用！！！
    while (*delim && *s != *delim) {
      delim++;
    }
    //因为delim绝对不会到 /0 ，所以s会在到达 /0 时跳出，
    if (*delim) { //若匹配上
      s++;
    } else
      stat = 0;
  }
  s_mem = s; //此时 *s 不为delimiters

  //找结尾
  while (*s) {
    delim = delimiters;
    while (*delim && *s != *delim) {
      delim++;
    }
    //跳出情况两种：
    // 1.*delim为 /0 ，此时说明 *s 与 delimiters没有一样，换下一个 *s
    // 2.*delim不为 /0 的情况下，*s与*delim匹配上，说明在此处应该断开
    if (*delim) {
      *s = '\0';
      char *t = s_mem;
      s_mem = s + 1;
      return t;
    }
    s++;
  }
  //跳出时，说明 s 中没有delimiters
  char *t = s_mem;
  s_mem = NULL;
  return t;
}